﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Web.SessionState;

using Yawf.Security.Entities;
using Yawf.Core.Exceptions;
using Yawf.Core.Utils;

namespace Yawf.Web.Utils {
	public class RequestWrapper {
		// Some internal variables
		private HttpRequest _Request = null;
		private HttpSessionState _Session = null;
		private bool _IsMultiPart = false;

		private HttpRequest Request { get { return _Request; } }
		private HttpSessionState Session { get { return _Session; } }
		private bool IsMultiPart { get { return _IsMultiPart; } }

		/// <summary>
		/// Constructor with request and session object
		/// </summary>
		/// <param name="request">HttpRequest object to use</param>
		/// <param name="session">HttpSessionState object to use</param>
		public RequestWrapper(HttpRequest request,HttpSessionState session) {
			_Request = request;
			_Session = session;

			if (Request != null && Request.HttpMethod == "POST") {
				_IsMultiPart = Request.HttpMethod.StartsWith("multipart/form-data");
			}
		}

		/// <summary>
		/// Gets the request parameter name as a String, null if not found
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>the value of parameter, null if not found</returns>
		private String GetParameter(String name) {					
  		String tmpValue = null;

			if (Request != null){
				tmpValue = Request.Form[name];

				if (tmpValue == null){
					tmpValue = Request.QueryString[name];
				}
			}
			
  		return tmpValue;
		}						// GetParameter

		/// <summary>
		/// Gets the request parameter name as a String array, null if not found
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>the array of values of parameter, null if not found</returns>
		public String[] GetParameterValues(String name) {
			String[] tmpValues = null;

			if (Request != null) {
				tmpValues = Request.Form.GetValues(name);

				if (tmpValues == null) {
					tmpValues = Request.QueryString.GetValues(name);
				}
			}

			return tmpValues;
		}									// GetParameterValues

		/// <summary>
		/// Gets the request parameter name as a DateTime structure, returns
		/// defaultValue if no parameter with name is found or the parameter
		/// cant be parsed as a DateTime using dd/MM/yyyy format
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <param name="defaultDate">Default date time to use if parameter not found</param>
		/// <returns>DateTime value</returns>
		public DateTime? GetDateTime(String name,DateTime? defaultValue) {
			return GetDateTime(name, "dd\\/MM\\/yyyy", defaultValue);
		}										// GetDateTime

		/// <summary>
		/// Gets the request parameter name as a DateTime structure, returns
		/// defaultValue if no parameter with name is found or the parameter
		/// cant be parsed as a DateTime using formatStr
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <param name="formatStr">Format string date shall be parsed as</param>
		/// <param name="defaultDate">Default date time to use if parameter not found</param>
		/// <returns>DateTime value</returns>
		public DateTime? GetDateTime(String name,String formatStr,DateTime? defaultValue) {
			DateTime? dateVal;
			
			dateVal = DateUtils.ParseDate(formatStr,GetParameter(name));
			if (dateVal == DateTime.MinValue){
				dateVal = defaultValue;
			}
			return dateVal;
		}										// GetDateTime

		/// <summary>
		/// Gets the request parameter as a String value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public String GetString(String name, String defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				return paramValue;
			}
			
			return defaultValue;
		}								// GetString

		/// <summary>
		/// Gets the request parameter as a Int32 value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public int GetInt(String name,int defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Int32 result;
				if (Int32.TryParse(paramValue,out result)) {
					return result;
				}
			}
			
			return defaultValue;
		}												// GetInt

		/// <summary>
		/// Gets the request parameter as a Int16 value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public short GetShort(String name,short defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Int16 result;
				if (Int16.TryParse(paramValue,out result)) {
					return result;
				}
			}
			
			return defaultValue;
		}											// GetShort

		/// <summary>
		/// Gets the request parameter as a byte value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public byte GetByte(String name,byte defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Byte result;
				if (Byte.TryParse(paramValue,out result)) {
					return result;
				}
			}
			
			return defaultValue;
		}									// GetByte

		/// <summary>
		/// Gets the request parameter as a char value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public char GetChar(String name,char defaultValue) {
			String paramValue = GetParameter(name);

			if (paramValue != null && paramValue.Length > 0) {
				return (paramValue.ToCharArray())[0];
			}

			return defaultValue;
		}									// GetByte

		/// <summary>
		/// Gets the request parameter as a Int64 value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public long GetLong(String name,long defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Int64 result;
				if (Int64.TryParse(paramValue,out result)) {
					return result;
				}
			}
			
			return defaultValue;
		}											// GetLong

		/// <summary>
		/// Gets the request parameter as a bool value, if request parameter
		/// not found this method returns default value.
		/// A value of yes,y,on,1,true,t is interpreted as true(ignoring case)
		/// All other values a interpreted as false
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public bool GetBool(String name,bool defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				return StringUtils.BoolValue(paramValue);
			}
			return defaultValue;
		}													// GetBool

		/// <summary>
		/// Gets the request parameter as a float value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public float GetFloat(String name,float defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Single result;
				if (Single.TryParse(paramValue,out result)) {
					return result;
				}
			}
	
			return defaultValue;
		}											// GetFloat

		/// <summary>
		/// Gets the request parameter as a double value, if request parameter
		/// not found this method returns default value
		/// </summary>
		/// <param name="name">Name of requets parameter to get</param>
		/// <param name="defaultValue">Default value to use if parameter not found</param>
		/// <returns>Value of request parameter, default value if not found</returns>
		public double GetDouble(String name,double defaultValue) {
			String paramValue = GetParameter(name);
	
			if(paramValue != null) {
				Double result;
				if (Double.TryParse(paramValue,NumberStyles.AllowDecimalPoint,NumberFormatInfo.InvariantInfo,out result)) {
					return result;
				}
			}
	
			return defaultValue;
		}  
	  
		/// <summary>
		/// Gets an uploaded file
		/// </summary>
		/// <param name="name">Name of file in request</param>
		/// <returns></returns>
		public HttpPostedFile GetFile(String name){
			HttpFileCollection files;
			int i;
 
 			files = GetFiles();
 			for(i = 0;files != null && i < files.Count; i++){
    		if(files.GetKey(i) == name){
					return files[i];
    		}
 			}

    	return null;
		}											// GetFile
	
		/// <summary>
		/// Gets all uploaded files in request
		/// </summary>
		/// <returns>A collection of HttpPostedFile objects</returns>
		public HttpFileCollection GetFiles(){
			if (Request != null){
				return Request.Files;
			}
		
			return null;
		}										// GetFiles

		/// <summary>
		/// Gets an array of string values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public String[] GetStrings(String name){
			return GetParameterValues(name);
		}								// GetStrings

		/// <summary>
		/// Gets an array of Byte values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Byte[] GetBytes(String name) {
			String[] strValues = GetParameterValues(name);
			Byte[] values = null;

			if (strValues != null) {
				values = new Byte[strValues.Length];
				for (int i = 0; i < strValues.Length; i++) {
					values[i] = 0;
					Byte.TryParse(strValues[i],out values[i]);
				}
			}

			return values;
		}										// GetBytes

		/// <summary>
		/// Gets an array of Int16 values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Int16[] GetShorts(String name) {
			String[] strValues = GetParameterValues(name);
			Int16[] values = null;

			if (strValues != null) {
				values = new Int16[strValues.Length];
				for (int i = 0; i < strValues.Length; i++) {
					values[i] = 0;
					Int16.TryParse(strValues[i],out values[i]);
				}
			}

			return values;
		}										// GetShorts

		/// <summary>
		/// Gets an array of Int32 values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Int32[] GetInts(String name) {
			String[] strValues = GetParameterValues(name);
			Int32[] values = null;
			
			if (strValues != null){
				values = new Int32[strValues.Length];
				for(int i=0; i < strValues.Length;i++){
					values[i] = 0;
					Int32.TryParse(strValues[i],out values[i]);
				}
			}
			
			return values;
		}										// GetInts

		/// <summary>
		/// Gets an array of Int64 values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Int64[] GetLongs(String name) {
			String[] strValues = GetParameterValues(name);
			Int64[] values = null;
			
			if (strValues != null){
				values = new Int64[strValues.Length];
				for(int i=0; i < strValues.Length;i++){
					values[i] = 0;
					Int64.TryParse(strValues[i],out values[i]);
				}
			}
			
			return values;
		}								// GetLongs

		/// <summary>
		/// Gets an array of double values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Double[] GetDoubles(String name) {
			String[] strValues = GetParameterValues(name);
			Double[] values = null;
			
			if (strValues != null){
				values = new Double[strValues.Length];
				for(int i=0; i < strValues.Length;i++){
					values[i] = 0;
					Double.TryParse(strValues[i],out values[i]);
				}
			}
			
			return values;
		}								// GetDoubles

		/// <summary>
		/// Gets an array of Float values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Single[] GetFloats(String name) {
			String[] strValues = GetParameterValues(name);
			Single[] values = null;

			if (strValues != null) {
				values = new Single[strValues.Length];
				for (int i = 0; i < strValues.Length; i++) {
					values[i] = 0;
					Single.TryParse(strValues[i],out values[i]);
				}
			}

			return values;
		}								// GetFloats

		/// <summary>
		/// Gets an array of Boolean values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Boolean[] GetBooleans(string name) {
			String[] strValues = GetParameterValues(name);
			Boolean[] values = null;

			if (strValues != null) {
				values = new Boolean[strValues.Length];
				for (int i = 0; i < strValues.Length; i++) {
					values[i] = StringUtils.BoolValue(strValues[i]);
				}
			}

			return values;
		}											// GetBooleans

		/// <summary>
		/// Gets an array of Char values of a request parameter, this method
		/// should be used when the posted form has the same variable name with the
		/// diferent values
		/// </summary>
		/// <param name="name">name of request parameter</param>
		/// <returns>An array of values for that parameter,null if parameter not found</returns>
		public Char[] GetChars(string name) {
			String[] strValues = GetParameterValues(name);
			Char[] values = null;

			if (strValues != null) {
				values = new Char[strValues.Length];
				for (int i = 0; i < strValues.Length; i++) {
					values[i] = Char.MinValue;
					if (strValues[i] != null && strValues[i].Length > 0) {
						values[i] = (strValues[i].ToCharArray())[0];
					}
				}
			}

			return values;
		}											// GetChars

		/// <summary>
		/// Saves an object in session
		/// </summary>
		/// <param name="theObject">Object to save</param>
		/// <param name="name">Key to use when saving in Session</param>
		public void SetSessionObject(Object theObject,String name){
			// Add object to session
			if (Session != null){
				Session.Add(name,theObject);
			}
		}							// SetSessionObject
	  
		/// <summary>
		/// Gets an object saved in session
		/// </summary>
		/// <param name="name">Key to use in Session</param>
		/// <returns>Object if found, null otherwise</returns>
		public Object GetSessionObject(String name){
			// Add object to session
			if (Session != null){
				return Session[name];
			}

			return null;
		}									// GetSessionObject

		/// <summary>
		/// Removes a earlier saved object in session
		/// </summary>
		/// <param name="name">Key to use in Session</param>
		/// <returns>Object removed, null, if not found in session</returns>
		public Object RemoveSessionObject(String name){
			Object theObject;
			
			// Get the saved articulo from session and remove it 
			theObject = GetSessionObject(name);
			if (Session != null) {
				Session.Remove(name);
			}
	
			return theObject;
		}						// RemoveSessionObject

		/// <summary>
		/// Gets a header value of this request
		/// </summary>
		/// <param name="headerName">name of header field</param>
		/// <returns>Value of header field</returns>
	  public String GetHeader(String headerName){
	  	if (Request != null){
				return Request.Headers[headerName];
			}
		
			// Using this metyhdo without request should throw an exception
			throw new YawfException(-1, "Method GetHeader not implemented without request object");
	  }

		/// <summary>
		/// Gets an array of all parameter names found in request
		/// </summary>
		/// <returns>An array of strings containing all names found in request</returns>
		public IList<String> GetParameterNames(){
			IList<String> paramNames = null;
			String[] tmpNames;
			int i;
			
			// Add all form names first
			if (Request != null){
				paramNames = new List<String>();
		 		tmpNames = Request.Form.AllKeys;
				for (i = 0; tmpNames != null && i < tmpNames.Length; i++) {
					paramNames.Add(tmpNames[i]);
				}
				
				// Add query names now
		 		tmpNames = Request.QueryString.AllKeys;
				for(i=0;tmpNames != null && i < tmpNames.Length;i++){
					paramNames.Add(tmpNames[i]);
				}
			}
		
			return paramNames;
		}														// GetParameterNames

		/// <summary>
		/// Gets an array of all parameter that starts with a prefix
		/// </summary>
		/// <param name="prefix">Prefix to filter parameters names on</param>
		/// <returns>An array of strings containing all names found in request that 
		/// starts with prefix</returns>
		public IList<String> GetParameterNames(String prefix) {
			IList<String> names,filteredNames;
			String tmpStr;

			names = GetParameterNames();
			filteredNames	= new List<String>();
			for (int i = 0; names != null && i < names.Count; i++) {
				tmpStr = names[i];
				if (prefix == null || prefix.Trim() == "" || tmpStr.StartsWith(prefix)) {
					filteredNames.Add(tmpStr);
				}
			}

			return filteredNames;
		}										// GetParameterNames

		/// <summary>
		/// Gets the resource part of the requested resoucee, eg the
		/// string after the ContextPath
		/// </summary>
		/// <returns>a string containing path to resource requested</returns>
		public String GetResourcePath(String webPartVariableName) {
			String uriStr,contextPath;
			String result = null;
			int index;

			// If we are inside a web part the page comes as a variable in request
			if (webPartVariableName != null && webPartVariableName.Trim() != "") {
				return Request[webPartVariableName];
			}

			// We are not insde a webpart, get resource from uri
			uriStr = Request.CurrentExecutionFilePath;
			contextPath = Request.ApplicationPath;
			if (uriStr != null) {
				index = uriStr.IndexOf(contextPath);
				if (index > -1) {
                    uriStr = uriStr.Substring(index + contextPath.Length);
                    if (uriStr.StartsWith("/")) {
                        result = "~" + uriStr;
                    } else {
                        result = "~/" + uriStr;
                    }
				}
			}

            return result;
		}								// GetResourcePath

		/// <summary>
		/// Gets user that is currently logged in into application
		/// </summary>
		/// <returns>Current user</returns>
		public void SetUser(IUser user) {
			if (user == null) {
				RemoveSessionObject("currentUser");
			} else {
				SetSessionObject(user, "currentUser");
			}
		}

		/// <summary>
		/// Gets user that is currently logged in into application
		/// </summary>
		/// <returns>Current user</returns>
		public IUser GetUser() {
			return (IUser)GetSessionObject("currentUser");
		}


		/// <summary>
		/// Gets name of server the application is running on
		/// It will add port number if port is different from 80
		/// </summary>
		/// <returns>A string of server application is running on</returns>
		public String GetServerName() {
			String serverName = "";
			String port;

			serverName = Request.ServerVariables["SERVER_NAME"];
			port = Request.ServerVariables["SERVER_PORT"];
			if (port != "80") {
				serverName = serverName + ":" + port;
			}
			
			return serverName;
		}								// GetServerName

		/// <summary>
		/// Gets application path.
		/// Returns the portion of the request URI that indicates the context of the request. The context path always comes first in a request URI. The path starts with a "/" character but does not end with a "/" character. For applications in the default (root) context, this method returns "".
		/// </summary>
		/// <returns>Returns the portion of the request URI that indicates the context of the request.</returns>
		public String GetContextPath() {
			String contextPath = Request.ApplicationPath;
			if (contextPath == "/") {
				return String.Empty;
			}
			return contextPath;
		}							// GetContextPath

		/// <summary>
		/// Gets Browser data
		/// </summary>
		/// <returns>HttpBrowserCapabilities object</returns>
		public HttpBrowserCapabilities GetBrowser() {
			return Request.Browser;
		}							// GetContextPath

		/// <summary>
		/// Gets the underliying HttpRequest
		/// </summary>
		/// <returns>HttpRequest object</returns>
		public HttpRequest RawRequest { get { return Request; } private set {} }
	}									// Class
}										// Namespace
